package ua.od.maxz;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

/**
 * User: ua.od.maxz
 * Date: Jun 22, 2010
 * Time: 1:55:45 PM
 */
public abstract class Killer {

    private Set<String> options = new HashSet<String>();

    public static final String OPTION_PRINT_STACKTRACE      = "-ps";
    public static final String OPTION_PRINT_PROCESSES       = "-pp";
    public static final String OPTION_SKIP_KILL_RESPONSE    = "-sr";
    public static final String OPTION_PRINT_RESULT          = "-pr";

    public Killer() {
    }

    public void run() {
        try {
            String processList = getProcessList();
            Collection<Integer> pIds = getPids(processList);
            if(pIds.size()==0) {
                throw new RuntimeException("Tomcat is not found!");
            }
            for (Integer pid : pIds) {
                kill(pid);
                if(options.contains(OPTION_PRINT_RESULT)) {
                    System.out.println("Tomcat with PID "+pid+" was killed");
                }
            }
        } catch (Exception e) {
            System.err.println("Error: " + e.getMessage());
            if(options.contains(OPTION_PRINT_STACKTRACE)) {
                e.printStackTrace();
            }
        }
    }

    private String getProcessList() throws Exception {
        StringBuilder ret = new StringBuilder();
        Process p = Runtime.getRuntime().exec(getCommandForTasksList());
        BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
        String line;
        boolean containsData = false;
        while ((line = input.readLine()) != null) {
            if(options.contains(OPTION_PRINT_PROCESSES)) {
                System.out.println("\t" + line);
            }
            ret.append(line);
            if(!containsData && line.trim().length()>0) {
                containsData = true;
            }
            if(containsData) {
                ret.append("\n");
            }
        }
        input.close();
        return ret.toString();
    }

    protected boolean kill(int pid) throws Exception {
        Process p = Runtime.getRuntime().exec(getKillCommand()+pid);
        BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
        String line;
        while ((line = input.readLine()) != null) {
            if(!options.contains(OPTION_SKIP_KILL_RESPONSE)) {
                System.out.println(" " + line);
            }
        }
        input.close(); //TODO WHAT IF ERROR? HOW TO KNOW?
        return true;
    }

    protected abstract String getKillCommand();

    protected abstract Collection<Integer> getPids(String processList);

    protected abstract String getCommandForTasksList();

    // ===================

    public void setOptions(Set<String> arguments) {
        options = arguments;
    }
}
